#include "dtu_modbus_poll.h"
#include "dtu_log.h"
#include "dtu_memory.h"
#include "dtu_modbus.h"
#include <string.h>
#include <ctype.h>

/**
 * @brief 将16进制字符串转换为字节数组
 * @param hex_string 16进制字符串
 * @param bytes 输出字节数组
 * @param max_bytes 最大字节数
 * @return 转换的字节数，失败返回-1
 */
int dtu_hex_string_to_bytes(const char* hex_string, uint8_t* bytes, size_t max_bytes)
{
    if (!hex_string || !bytes) {
        return -1;
    }
    
    size_t hex_len = strlen(hex_string);
    if (hex_len % 2 != 0) {
        DTU_LOG_ERROR("Hex string length must be even");
        return -1;
    }
    
    size_t byte_count = hex_len / 2;
    if (byte_count > max_bytes) {
        DTU_LOG_ERROR("Hex string too long, max %zu bytes", max_bytes);
        return -1;
    }
    
    for (size_t i = 0; i < byte_count; i++) {
        char hex_byte[3] = {hex_string[i*2], hex_string[i*2+1], '\0'};
        
        /* 验证是否为有效的16进制字符 */
        if (!isxdigit(hex_byte[0]) || !isxdigit(hex_byte[1])) {
            DTU_LOG_ERROR("Invalid hex character at position %zu", i*2);
            return -1;
        }
        
        /* 转换为字节 */
        bytes[i] = (uint8_t)strtol(hex_byte, NULL, 16);
    }
    
    return (int)byte_count;
}

/**
 * @brief 将字节数组转换为16进制字符串
 * @param bytes 字节数组
 * @param byte_count 字节数
 * @param hex_string 输出16进制字符串
 * @param max_string_len 最大字符串长度
 * @return DTU_OK 成功，其他值失败
 */
dtu_error_t dtu_bytes_to_hex_string(const uint8_t* bytes, size_t byte_count, 
                                    char* hex_string, size_t max_string_len)
{
    if (!bytes || !hex_string) {
        return DTU_ERROR_INVALID_PARAM;
    }
    
    if (byte_count * 2 + 1 > max_string_len) {
        DTU_LOG_ERROR("Output string buffer too small");
        return DTU_ERROR;
    }
    
    for (size_t i = 0; i < byte_count; i++) {
        snprintf(hex_string + i*2, 3, "%02X", bytes[i]);
    }
    
    return DTU_OK;
}

/**
 * @brief 处理轮询字符串，添加CRC校验
 * @param poll_string 原始轮询字符串(16进制)
 * @param crc_enable 是否启用CRC
 * @param output_bytes 输出字节数组
 * @param max_output_bytes 最大输出字节数
 * @return 输出字节数，失败返回-1
 */
int dtu_process_poll_string(const char* poll_string, bool crc_enable, 
                           uint8_t* output_bytes, size_t max_output_bytes)
{
    if (!poll_string || !output_bytes) {
        return -1;
    }
    
    /* 转换16进制字符串为字节数组 */
    uint8_t temp_bytes[256];
    int byte_count = dtu_hex_string_to_bytes(poll_string, temp_bytes, sizeof(temp_bytes));
    if (byte_count < 0) {
        return -1;
    }
    
    /* 检查输出缓冲区大小 */
    size_t required_size = byte_count + (crc_enable ? 2 : 0);
    if (required_size > max_output_bytes) {
        DTU_LOG_ERROR("Output buffer too small, need %zu bytes", required_size);
        return -1;
    }
    
    /* 复制原始数据 */
    memcpy(output_bytes, temp_bytes, byte_count);
    
    /* 如果启用CRC，计算并添加CRC16校验 */
    if (crc_enable) {
        uint16_t crc = dtu_modbus_crc16(temp_bytes, byte_count);
        output_bytes[byte_count] = crc & 0xFF;        /* CRC低字节 */
        output_bytes[byte_count + 1] = (crc >> 8) & 0xFF; /* CRC高字节 */
        byte_count += 2;
    }
    
    return byte_count;
}

/**
 * @brief 执行Modbus轮询
 * @param device_config 设备配置
 * @param response_data 响应数据缓冲区
 * @param max_response_len 最大响应长度
 * @return 响应数据长度，失败返回-1
 */
int dtu_execute_modbus_poll(const modbus_device_config_t* device_config, 
                           uint8_t* response_data, size_t max_response_len)
{
    if (!device_config || !response_data) {
        return -1;
    }
    
    if (!device_config->enabled) {
        DTU_LOG_DEBUG("Device %s is disabled", device_config->name);
        return 0;
    }
    
    /* 处理轮询字符串 */
    uint8_t poll_bytes[256];
    int poll_len = dtu_process_poll_string(device_config->poll_string, 
                                          device_config->crc_enable,
                                          poll_bytes, sizeof(poll_bytes));
    if (poll_len < 0) {
        DTU_LOG_ERROR("Failed to process poll string for device %s", device_config->name);
        return -1;
    }
    
    /* 记录发送的数据 */
    char hex_log[512];
    dtu_bytes_to_hex_string(poll_bytes, poll_len, hex_log, sizeof(hex_log));
    DTU_LOG_INFO("Polling device %s with data: %s", device_config->name, hex_log);
    
    /* TODO: 实际的串口发送和接收逻辑 */
    /* 这里需要根据device_config->serial_port选择RS485或RS232 */
    /* 发送poll_bytes数据，接收响应到response_data */
    
    /* 模拟响应数据 */
    const char* mock_response = "010300020001";
    int response_len = dtu_hex_string_to_bytes(mock_response, response_data, max_response_len);
    
    if (response_len > 0) {
        char response_hex[512];
        dtu_bytes_to_hex_string(response_data, response_len, response_hex, sizeof(response_hex));
        DTU_LOG_INFO("Received response from device %s: %s", device_config->name, response_hex);
    }
    
    return response_len;
}

/**
 * @brief 验证16进制字符串格式
 * @param hex_string 16进制字符串
 * @return true 有效，false 无效
 */
bool dtu_validate_hex_string(const char* hex_string)
{
    if (!hex_string) {
        return false;
    }
    
    size_t len = strlen(hex_string);
    if (len == 0 || len % 2 != 0) {
        return false;
    }
    
    for (size_t i = 0; i < len; i++) {
        if (!isxdigit(hex_string[i])) {
            return false;
        }
    }
    
    return true;
}

/**
 * @brief 格式化轮询字符串显示
 * @param poll_string 轮询字符串
 * @param formatted_output 格式化输出缓冲区
 * @param max_output_len 最大输出长度
 * @return DTU_OK 成功，其他值失败
 */
dtu_error_t dtu_format_poll_string(const char* poll_string, char* formatted_output, size_t max_output_len)
{
    if (!poll_string || !formatted_output) {
        return DTU_ERROR_INVALID_PARAM;
    }
    
    size_t len = strlen(poll_string);
    if (len == 0) {
        DTU_STRNCPY(formatted_output, "Empty", max_output_len);
        return DTU_OK;
    }
    
    /* 每两个字符添加一个空格，便于阅读 */
    size_t output_pos = 0;
    for (size_t i = 0; i < len && output_pos < max_output_len - 1; i += 2) {
        if (i > 0 && output_pos < max_output_len - 2) {
            formatted_output[output_pos++] = ' ';
        }
        
        if (i + 1 < len && output_pos < max_output_len - 3) {
            formatted_output[output_pos++] = poll_string[i];
            formatted_output[output_pos++] = poll_string[i + 1];
        }
    }
    
    formatted_output[output_pos] = '\0';
    return DTU_OK;
}
